<template>
  <el-form ref="formRef" :model="dynamicForm" label-width="120px">
    <el-form-item v-for="item in labels" :prop="item.field" :label="item.label" :rules="getFormRules(item)">
      <!-- input -->
      <el-input v-if="identifyType(item, 'text')" v-model="dynamicForm[item.field]" @change="formChangeHandler"
        :disabled="item.disabled" />

      <!-- password -->
      <el-input v-else-if="identifyType(item, 'password')" type="password" v-model="dynamicForm[item.field]"
        @change="formChangeHandler" :disabled="item.disabled" :show-password="item.showPassword" />

      <!-- textarea -->
      <el-input v-else-if="identifyType(item, 'textarea')" v-model="dynamicForm[item.field]" type="textarea"
        @change="formChangeHandler" :disabled="item.disabled" />

      <!-- input-number -->
      <el-input-number v-else-if="identifyType(item, 'inputnumber')" v-model="dynamicForm[item.field]" :min="item.min"
        :max="item.max" controls-position="right" @change="formChangeHandler" />

      <!-- select-input -->
      <el-input v-else-if="identifyType(item, 'selectinput')" v-model="dynamicForm[item.field]">
        <template #prepend>
          <el-select v-model="select" placeholder="Select" style="width: 115px">
            <el-option label="Restaurant" value="1" />
            <el-option label="Order No." value="2" />
            <el-option label="Tel" value="3" />
          </el-select>
        </template>
        <template #append>
          <el-button :icon="Search" />
        </template>
      </el-input>

      <!-- select -->
      <el-select v-else-if="identifyType(item, 'select')" v-model="dynamicForm[item.field]"
        :placeholder="`请选择${item.label}`" :disabled="item.disabled" @change="formChangeHandler">
        <template v-for="option in (item?.dict || [])">
          <el-option :label="option.name" :value="option.value" />
        </template>
      </el-select>

      <!-- date-picker -->
      <el-date-picker v-else-if="identifyType(item, 'datepicker')" v-model="dynamicForm[item.field]" type="date"
        :placeholder="`请选择${item.label}`" style="width: 100%" :disabled="item.disabled" />

      <!-- switch -->
      <el-switch v-else-if="identifyType(item, 'switch')" v-model="dynamicForm[item.field]" :disabled="item.disabled" />

      <!-- radio -->
      <el-radio-group v-else-if="identifyType(item, 'radio')" v-model="dynamicForm[item.field]"
        :disabled="item.disabled" @change="formChangeHandler">
        <template v-for="option in (item?.dict || [])">
          <el-radio :label="option.value" :name="item.field">{{ option.label }}</el-radio>
        </template>
      </el-radio-group>

      <!-- checkbox -->
      <el-checkbox-group v-else-if="identifyType(item, 'checkbox')" v-model="dynamicForm[item.field]"
        :disabled="item.disabled" @change="formChangeHandler">
        <template v-for="option in (item?.dict || [])">
          <el-checkbox :label="option.value" :name="item.field">{{ option.label }}</el-checkbox>
        </template>
      </el-checkbox-group>

      <!-- image -->
      <el-image v-else-if="identifyType(item, 'image')" :src="dynamicForm[item.field]" fit="fit"
        style="width: 100px; height: 100px" />

      <!-- other -->
      <template v-else>
        {{ dynamicForm[item.field] }}
      </template>
    </el-form-item>

    <el-form-item>
      <el-button v-if="config?.reset" type="warning" @click="resetForm(formRef)" plain>重置</el-button>
      <slot></slot>
    </el-form-item>
  </el-form>
</template>

<script setup>
import { ref, reactive, defineProps, watch, getCurrentInstance } from 'vue';

const { proxy } = getCurrentInstance();
const emit = defineEmits(['emit-util-form']);

const props = defineProps({
  labels: { type: Array, required: true, default: () => [] },
  formData: { type: Object, required: false, default: () => ({}) },
  config: {
    type: Object,
    required: false,
    default: () => ({
      reset: false,
      clearable: false
    })
  }
});

const formRef = ref();
const dynamicForm = reactive({});

watch(() => props.config, cfg => {
  if (cfg.clearable) {
    resetForm(formRef.value);
  }
}, { immediate: true, deep: true });

watch(() => props.formData, val => {
  setDynamicForm(val, props.labels);
}, { immediate: true, deep: true });

const getFormRules = item => {
  if (!proxy.$utils.isValidValue(item)) {
    return []
  }
  const { label, required = false, labelType } = item;
  const inputWidget = ['text', 'password', 'textarea', 'inputnumber'];
  const selectWidget = ['datepicker', 'switch', 'checkbox', 'radio'];
  const type = labelType.toLocaleLowerCase();
  let message = '';
  let trigger = null;

  if (inputWidget.includes(type)) {
    message = '请正确输入' + label;
    trigger = ['blur', 'change'];
  } else if (selectWidget.includes(type)) {
    message = '请选择' + label;
    trigger = 'blur';
  } else {
    message = label + '不能为空';
    trigger = 'blur';
  }

  return [
    { required, message, trigger }
  ]
}

function resetForm(formEl) {
  if (!formEl) return
  formEl.resetFields()
}

function identifyType(item, type, field = 'labelType') {
  return (item?.[field] || '').toLocaleLowerCase() === type;
}

function formChangeHandler() {
  emit('emit-util-form', { form: dynamicForm });
}

function setDynamicForm(data = {}, labels = []) {
  labels.forEach(({ field }) => {
    dynamicForm[field] = data[field];
  });
}
</script>